package jt.classic.system.workflow.impl;

import jt.classic.system.group.IGroup;
import jt.classic.system.user.IUser;
import jt.classic.system.workflow.WActivity;
import jt.classic.system.workflow.WFlow;
import jt.classic.system.workflow.WInner;
import jt.classic.system.workflow.WInstance;
import jt.classic.system.workflow.WNumber;

import org.limp.basework.AbstractSimpleBean;

import org.limp.mine.DateTrimmer;
import org.limp.mine.HTMLTool;
import org.limp.mine.annex.AnnexInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * 流程实例接口实现类
 *
 * @author bizkit
 *
 */
public class WInstanceImpl extends AbstractSimpleBean implements WInstance {
    private IUser creator;
    private IGroup group;
    private String creatorid;
    private String id;
    private String creatorname;
    private String unitid;
    private String unitname;
    private String starttime;
    private String endtime;
    private String lmtime;
    private int state;
    private WFlow flow;
    private List activitys;
    private WActivity maxactivity;
    private String sequence;
    private WNumber number;
    private AnnexInfo doc;

    public IUser icreator() {
        // TODO Auto-generated method stub
        return this.creator;
    }

    public String icreatorid() {
        // TODO Auto-generated method stub
        return this.creatorid;
    }

    public String icreatorname() {
        // TODO Auto-generated method stub
        return this.creatorname;
    }

    public String id() {
        // TODO Auto-generated method stub
        return this.id;
    }

    public String iendtime() {
        // TODO Auto-generated method stub
        return this.endtime;
    }

    public WFlow iflow() {
        // TODO Auto-generated method stub
        return this.flow;
    }

    public String ilmtime() {
        // TODO Auto-generated method stub
        return this.lmtime;
    }

    public String istarttime() {
        // TODO Auto-generated method stub
        return this.starttime;
    }

    public int istate() {
        // TODO Auto-generated method stub
        return this.state;
    }

    public IGroup iunit() {
        return this.group;
    }

    public String iunitid() {
        // TODO Auto-generated method stub
        return this.unitid;
    }

    public String iunitname() {
        // TODO Auto-generated method stub
        return this.unitname;
    }

    public WNumber inumber() {
        return this.number;
    }

    public AnnexInfo idoc() {
        return this.doc;
    }

    public List iactivitylist() {
        return this.activitys;
    }

    public List iactivitylist4mychildren(String aid) {
        List list = new ArrayList();

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity temp = (WActivity) this.activitys.get(i);

                if (!temp.id().equals(aid) && temp.ilast().id().equals(aid)) {
                    list.add(temp);
                }
            }
        }

        return list;
    }

    public WActivity iactivity(String id) {
        WActivity activity = null;

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity temp = (WActivity) this.activitys.get(i);

                if (temp.id().equals(id)) {
                    activity = temp;

                    break;
                }
            }
        }

        return activity;
    }

    public boolean ininner() {
        WActivity act = this.imaxactivity();

        return act.istep().inner() > 0;
    }

    public WInner inowinner() {
        WInner inner = null;

        return inner;
    }

    public boolean innerisok(int inner, String process) {
        List list = this.inner4out(inner, process);

        boolean rnt = true;

        for (int i = 0; i < list.size(); i++) {
            WActivity act = (WActivity) list.get(i);

            if ((act.istate() == 0) || (act.istate() == 1)) {
                rnt = false;

                break;
            }
        }

        return rnt;
    }

    public List iactivitylistinner(int inner) {
        List list = new ArrayList();

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity temp = (WActivity) this.activitys.get(i);

                if (temp.istep().inner() == inner) {
                    list.add(temp);
                }
            }
        }

        return list;
    }

    public List iactivitylistinner(int inner, String process) {
        List list = new ArrayList();

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity temp = (WActivity) this.activitys.get(i);

                if (((temp.istep().inner() == inner) &&
                        temp.iprocess().equals(process))) {
                    list.add(temp);
                }
            }
        }

        return list;
    }

    public List iactivitylistinner(int inner, String process, String group) {
        List list = new ArrayList();

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity temp = (WActivity) this.activitys.get(i);

                if ((temp.istep().inner() == inner) &&
                        temp.iprocess().equals(process) &&
                        temp.igroup().equals(group)) {
                    list.add(temp);
                }
            }
        }

        return list;
    }

    public WActivity imaxactivity() {
        if (this.maxactivity == null) {
            if ((this.activitys != null) && !this.activitys.isEmpty()) {
                int count = this.activitys.size() - 1;

                while (count >= 0) {
                    WActivity act = (WActivity) this.activitys.get(count);

                    if (act.istep().itype() != 2) {
                        this.maxactivity = act;

                        break;
                    }

                    count--;
                }
            }
        }

        return this.maxactivity;
    }

    public boolean iotherinnerisok(int inner, String process, String group) {
        List list = this.iactivitylistinner(inner, process);

        boolean rnt = true;

        for (int i = 0; i < list.size(); i++) {
            WActivity act = (WActivity) list.get(i);

            if (!act.igroup().equals(group) && (act.istep().itype() != 2) &&
                    ((act.istate() == 0) || (act.istate() == 1))) {
                rnt = false;

                break;
            }
        }

        return rnt;
    }

    public List iotherinner(int inner, String process, String group) {
        List iotherinner = new ArrayList();

        List list = this.iactivitylistinner(inner, process);

        for (int i = 0; i < list.size(); i++) {
            WActivity act = (WActivity) list.get(i);

            if (!act.igroup().equals(group)) {
                iotherinner.add(act);
            }
        }

        return iotherinner;
    }

    public List iotherinner4out(int inner, String process, String group) {
        List l = new ArrayList();
        String[] groups = this.innerprocessgroup(inner, process);

        for (int i = 0; i < groups.length; i++) {
            if (!groups[i].equals(group)) {
                List list = this.iactivitylistinner(inner, process, groups[i]);
                l.add(list.get(list.size() - 1));
            }
        }

        return l;
    }

    public List iotherinner4in(int inner, String process, String group) {
        List l = new ArrayList();
        String[] groups = this.innerprocessgroup(inner, process);

        for (int i = 0; i < groups.length; i++) {
            if (!groups[i].equals(group)) {
                List list = this.iactivitylistinner(inner, process, groups[i]);
                l.add(list.get(0));
            }
        }

        return l;
    }

    public List inner4out(int inner, String process) {
        List l = new ArrayList();
        String[] groups = this.innerprocessgroup(inner, process);

        for (int i = 0; i < groups.length; i++) {
            List list = this.iactivitylistinner(inner, process, groups[i]);
            l.add(list.get(list.size() - 1));
        }

        return l;
    }

    public WActivity inner4out(int inner, String process, String group) {
        List list = this.iactivitylistinner(inner, process, group);

        return list.isEmpty() ? null : (WActivity) list.get(list.size() - 1);
    }

    public List inner4in(int inner, String process) {
        List l = new ArrayList();
        String[] groups = this.innerprocessgroup(inner, process);

        for (int i = 0; i < groups.length; i++) {
            List list = this.iactivitylistinner(inner, process, groups[i]);
            l.add(list.get(0));
        }

        return l;
    }

    public WActivity inner4before(String process) {
        WActivity act = null;

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity temp = (WActivity) this.activitys.get(i);

                if (temp.iprocess().equals(process) &&
                        (temp.istep().inner() == 0)) {
                    act = temp;

                    break;
                }
            }
        }

        return act;
    }

    public String[] innerprocessgroup(int inner, String process) {
        List list = this.iactivitylistinner(inner, process);

        String str = "";

        for (int i = 0; i < list.size(); i++) {
            WActivity act = (WActivity) list.get(i);

            if (str.indexOf(act.igroup() + ",") == -1) {
                str += (act.igroup() + ",");
            }
        }

        if (!str.equals("")) {
            str = str.substring(0, str.length() - 1);
        }

        return str.split(",");
    }

    public String[] innerprocess(int inner) {
        List list = this.iactivitylistinner(inner);

        String str = "";

        for (int i = 0; i < list.size(); i++) {
            WActivity act = (WActivity) list.get(i);

            if (str.indexOf(act.iprocess() + ",") == -1) {
                str += (act.iprocess() + ",");
            }
        }

        if (!str.equals("")) {
            str = str.substring(0, str.length() - 1);
        }

        return str.split(",");
    }

    public String isequence() {
        return this.sequence;
    }

    public String toXML(int type) {
        StringBuffer xml = new StringBuffer();
        xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        xml.append("<InstanceProcess>\n");
        xml.append("<insid>" + this.id + "</insid>\n");
        xml.append("<flowtype>" + this.flow.itype() + "</flowtype>\n");
        xml.append("<flowname>" + this.flow.iname() + "</flowname>\n");
        xml.append("<creator>" + this.creatorname + "</creator>\n");
        xml.append("<unit>" + this.unitname + "</unit>\n");
        xml.append("<post></post>\n");
        xml.append("<stime>" +
            DateTrimmer.toYMD(DateTrimmer.getYMD_LBL(this.istarttime())) +
            "</stime>\n");

        if ((this.activitys != null) && !this.activitys.isEmpty()) {
            for (int i = 0; i < this.activitys.size(); i++) {
                WActivity act = (WActivity) this.activitys.get(i);

                xml.append("<Activity>\n");
                xml.append("<id>" + act.id() + "</id>\n");
                xml.append("<title>" + act.ititle() + "</title>\n");
                xml.append("<sid>" + act.istep().id() + "</sid>\n");
                xml.append("<sno>" + act.istep().ino() + "</sno>\n");
                xml.append("<status>" + act.istate() + "</status>\n");
                xml.append("<flowtype>" + act.instance().iflow().itype() +
                    "</flowtype>\n");
                xml.append("<type>" + act.itype() + "</type>\n");
                xml.append("<stime>" +
                    DateTrimmer.toYMDHMS(DateTrimmer.getYMDHMS_LBL(
                            act.istarttime())) + "</stime>\n");
                xml.append("<etime>" +
                    DateTrimmer.toYMDHMS(DateTrimmer.getYMDHMS_LBL(
                            act.iendtime())) + "</etime>\n");
                xml.append("<ltime>" +
                    DateTrimmer.toYMDHMS(DateTrimmer.getYMDHMS_LBL(
                            act.ilmtime())) + "</ltime>\n");
                xml.append("<lock>" + act.ilock() + "</lock>\n");
                xml.append("<lockid>" +
                    ((act.ilocker() != null) ? act.ilocker().id() : "0") +
                    "</lockid>\n");
                xml.append("<lockname>" +
                    ((act.ilocker() != null) ? act.ilocker().iname() : "") +
                    "</lockname>\n");
                xml.append("<executorid>" +
                    ((act.iexecutor().iuser() != null)
                    ? act.iexecutor().iuser().id() : "") + "</executorid>\n");
                xml.append("<executorname>" +
                    ((act.iexecutor() != null) ? act.iexecutor().iusername() : "") +
                    "</executorname>\n");
                xml.append("<executorunitid>" +
                    ((act.iexecutor().iunit() != null)
                    ? act.iexecutor().iunit().id() : "") +
                    "</executorunitid>\n");
                xml.append("<executorunitname>" +
                    ((act.iexecutor().iunit() != null)
                    ? act.iexecutor().iunit().iname() : "") +
                    "</executorunitname>\n");
                xml.append("</Activity>\n");

                /*办结实例,将最后流转活动视为结束环节流转活动(实际功能设计上并不存在结束环节对应的流转实例)*/
                if ((this.state == 1) && (i == (this.activitys.size() - 1))) {
                    xml.append("<Activity>\n");
                    xml.append("<id>" + act.id() + "</id>\n");
                    xml.append("<title>" + act.ititle() + "</title>\n");
                    xml.append("<sid>" +
                        act.instance().iflow().istep4end().id() + "</sid>\n");
                    xml.append("<sno>" +
                        act.instance().iflow().istep4end().ino() + "</sno>\n");
                    xml.append("<status>" + act.istate() + "</status>\n");
                    xml.append("<flowtype>" + act.instance().iflow().itype() +
                        "</flowtype>\n");
                    xml.append("<type>" + act.itype() + "</type>\n");
                    xml.append("<stime>" +
                        DateTrimmer.toYMDHMS(DateTrimmer.getYMDHMS_LBL(
                                act.istarttime())) + "</stime>\n");
                    xml.append("<etime>" +
                        DateTrimmer.toYMDHMS(DateTrimmer.getYMDHMS_LBL(
                                act.iendtime())) + "</etime>\n");
                    xml.append("<ltime>" +
                        DateTrimmer.toYMDHMS(DateTrimmer.getYMDHMS_LBL(
                                act.ilmtime())) + "</ltime>\n");
                    xml.append("<lock>" + act.ilock() + "</lock>\n");
                    xml.append("<lockid>" +
                        ((act.ilocker() != null) ? act.ilocker().id() : "0") +
                        "</lockid>\n");
                    xml.append("<lockname>" +
                        ((act.ilocker() != null) ? act.ilocker().iname() : "") +
                        "</lockname>\n");
                    xml.append("<executorid>" +
                        ((act.iexecutor().iuser() != null)
                        ? act.iexecutor().iuser().id() : "") +
                        "</executorid>\n");
                    xml.append("<executorname>" +
                        ((act.iexecutor() != null)
                        ? act.iexecutor().iusername() : "") +
                        "</executorname>\n");
                    xml.append("<executorunitid>" +
                        ((act.iexecutor().iunit() != null)
                        ? act.iexecutor().iunit().id() : "") +
                        "</executorunitid>\n");
                    xml.append("<executorunitname>" +
                        ((act.iexecutor().iunit() != null)
                        ? act.iexecutor().iunit().iname() : "") +
                        "</executorunitname>\n");

                    xml.append("</Activity>\n");
                }
            }
        }

        xml.append("</InstanceProcess>");

        return xml.toString();
    }

    public void reload(Map info) {
        super.reload(info);

        this.id = (String) info.get("INS_ID");
        this.creator = (IUser) info.get("INS_CREATOR");
        this.creatorid = (String) info.get("INS_CREATORID");
        this.creatorname = (String) info.get("INS_CREATORNAME");
        this.starttime = (String) info.get("INS_START");
        this.endtime = (String) info.get("INS_END");
        this.lmtime = (String) info.get("INS_LIMIT");
        this.group = (IGroup) info.get("INS_CUNIT");
        this.unitid = (String) info.get("INS_CUNITID");
        this.unitname = (String) info.get("INS_CUNITNAME");
        this.flow = (WFlow) info.get("WFLOW");
        this.state = Integer.parseInt((String) info.get("INS_STATE"));
        this.activitys = (List) info.get("ACTIVITYLIST");
        this.sequence = (String) info.get("INS_SEQUENCE");
        this.doc = (AnnexInfo) info.get("DOC");
        this.number = (WNumber) info.get("NUMBER");
    }
}
